const memorize = <F extends (...args: readonly any[]) => any>(fn: F): F => {
    let cache: any = {}
    //@ts-ignore
    return (...args: readonly any[]): any => {
        const key = String(args)
        if (!(key in cache)) {
            console.log(`new key: ${args}`)
            cache[key] = fn(...args)
        }
        return cache[key]
    }
}

const add = (a: number, b: number) => a + b;

const cached_add = memorize(add)

console.log(cached_add(1, 2))
console.log(cached_add(2, 3))
console.log(cached_add(1, 2))